package com.daxia.bumall.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

import com.daxia.bumall.basemodel.CoreUser;
import com.daxia.bumall.common.Sex;
import com.daxia.bumall.common.UserType;
import com.daxia.bumall.daobase.GenericDAOHibernate;
import com.daxia.bumall.dto.UserDTO;
import com.daxia.bumall.model.User;
import com.daxia.bumall.support.Page;
import com.daxia.bumall.util.DateUtils;

@Repository
public class UserDAO extends GenericDAOHibernate<User> implements ICoreUserDAO {

    public List<User> find(UserDTO dto, Page page) {
        StringBuilder hql = new StringBuilder();
        List<Object> paras = new ArrayList<Object>();
        hql.append("From User n where 1 = 1 ");
        if (dto.getId() != null) {
            hql.append(" and n.id = ? ");
            paras.add(dto.getId());
        }
        if (StringUtils.isNotBlank(dto.getUsername())) {
            hql.append(" and n.username = ? ");
            paras.add(dto.getUsername());
        }					
        if (StringUtils.isNotBlank(dto.getMobile())) {
        	hql.append(" and n.mobile = ? ");
        	paras.add(dto.getMobile());
        }
        if (StringUtils.isNotBlank(dto.getPassword())) {
        	hql.append(" and n.password = ? ");
        	paras.add(dto.getPassword());
        }
        if (dto.getType() != null) {
            hql.append(" and n.type = ? ");
            paras.add(dto.getType());
        }
        if (null!=dto.getProvince()) {
        	if (dto.getProvince().getId() != null&&dto.getProvince().getId()!=-1) {
	            hql.append(" and n.province.id = ? ");
	            paras.add(dto.getProvince().getId());
        	}
        }			
        if (dto.getCity() != null) {
        	if (dto.getCity().getId() != null&&dto.getCity().getId()!=-1) {
	            hql.append(" and n.city.id = ? ");
	            paras.add(dto.getCity().getId());
        	}
        }			
        if (dto.getDepartment() != null) {
        	if (dto.getDepartment().getId() != null) {
        		hql.append(" and n.department.id = ? ");
        		paras.add(dto.getDepartment().getId());
        	}
        }
        if (StringUtils.isNotBlank(dto.getNickName())) {
            hql.append(" and n.nickName = ? ");
            paras.add(dto.getNickName());
        }					
        if (StringUtils.isNotBlank(dto.getOpenid())) {
            hql.append(" and n.openid = ? ");
            paras.add(dto.getOpenid());
        }		
        if (StringUtils.isNotBlank(dto.getUnionid())) {
            hql.append(" and n.unionid = ? ");
            paras.add(dto.getUnionid());
        }		
        if (StringUtils.isNotBlank(dto.getSearchTerm())) {
        	hql.append(" and (n.username like ? or"
        			+ " n.nickName like ? "
        			+ " or n.realName like ?"
        			+ " or n.mobile like ?"
        			+ ") ");
        	paras.add("%" + dto.getSearchTerm() + "%");
        	paras.add("%" + dto.getSearchTerm() + "%");
        	paras.add("%" + dto.getSearchTerm() + "%");
        	paras.add("%" + dto.getSearchTerm() + "%");
        }
        if (dto.getParent() != null && dto.getParent().getId() != null) {
        	hql.append(" and n.parent.id = ? ");
        	paras.add(dto.getParent().getId());
        }
        if (dto.getSeedUser()) {
        	if (dto.getSeedStatus() != null) {
        		hql.append(" and n.seedStatus = ? ");
        		paras.add(dto.getSeedStatus());
        	} else {
        		hql.append(" and n.seedStatus is not null ");
        	}
        } 
        if (dto.getRecUser() != null) {
        	if (dto.getRecUser().getId() != null) {
        		hql.append(" and n.recUser.id = ? ");
        		paras.add(dto.getRecUser().getId());
        	}
        }
        
        if (dto.isExcludeSelf()) {
        	hql.append(" and n.id != ? ");
        	paras.add(dto.getExcludeUserId());
        }

        if (dto.getQuerySubacount() != null && dto.getQuerySubacount()) {
        	hql.append(" and n.type in (?, ?) ");
        	paras.add(UserType.DecorateCompany.getValue());
        	paras.add(UserType.Designer.getValue());
        }
        
        if (StringUtils.isNotBlank(dto.getOgSessionId())) {
        	hql.append(" and n.ogSessionId = ? ");
        	paras.add(dto.getOgSessionId());
        }
        
        
        hql.append(" and n.deleted != 1 ");
        
        hql.append(" order by n.id desc ");
        System.out.println("hql: " + hql);
        return super.find(hql.toString(), paras.toArray(), page);
    }
    
    public User findOne(UserDTO dto) {
		Page page = new Page();
		page.setPageSize(1);
		page.setPage(1);
		
		List<User> list = this.find(dto, page);
	    return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    @Override
    public CoreUser loadUserByUsername(String username) {
        UserDTO query = new UserDTO();
        query.setUsername(username);
        return this.findOne(query);
    }

    public int countOfRankGreaterThan(Integer consumeRank) {
        String sql = "select count(*) from user where consumeRank > ? ";
        return super.countBySql(sql, new Object[] {consumeRank});
    }
    
    public int countOfRankLessThan(Integer consumeRank) {
        String sql = "select count(*) from user where consumeRank < ? ";
        return super.countBySql(sql, new Object[] {consumeRank});
    }

    public void addTransferrableShareCoupon(Long id, Double amount) {
        String hql = "update User set transferrableShareCoupon = transferrableShareCoupon + ? where id = ?";
        super.executeUpdate(hql, new Object[] {amount, id});
    }
    
    public User findSeq(UserDTO dto) {
    	StringBuffer buff = new StringBuffer();
		List<Object> paras = new ArrayList<Object>();
		buff.append("SELECT Id,IFNULL(MAX(seq),0) Seq from user n where 1=1 ");
		if (dto.getType() != null) {
			buff.append(" and n.type = ? ");
            paras.add(dto.getType());
        }
		List<User> list = super.findBySQL(buff.toString(), paras.toArray(), User.class);
		return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }
    
    public User findByMerchant(Long merchantId) {
        UserDTO q = new UserDTO();
        return this.findOne(q);
    }

    public User findUserByMobile(String mobile) {
    	if (StringUtils.isBlank(mobile)) {
    		return null;
    	}
        UserDTO q = new UserDTO();
        q.setMobile(mobile);
        return this.findOne(q);
    }
    
    @Override
    public Long create(User t) {
    	t.setCreatetime(new Date());
    	if (t.getType() == null) {
    		t.setType(UserType.Manager.getValue());
    	}
    	if (t.getSex() == null) {
    		t.setSex(Sex.Male.getValue());
    	}
    	return super.create(t);
    }
    
    @Override
    public void update(User t) {
    	super.update(t);
    }
    
    @Override
    public void deleteById(Serializable id) {
    	String hql = "update User set deleted = true where id = ? and username =concat('【删】', username) ";
    	super.executeUpdate(hql, new Object[] {id});
    }

	public void updateDepartmentToNull(Long departmentId) {
		String hql = " update User set department = null where department.id = ? ";
		super.executeUpdate(hql, new Object[] {departmentId});
	}

	public int countByTypeAndCity(int type, Long cityId) {
		String hql = "select count(*) from User where type = ? and city.id = ?";
		return super.countByHql(hql, new Object[] {type, cityId});
	}

	public int countSubAccounts(Long parentUserId, Date startDate, Date endDate) {
		String hql = "select count(*) from User where parent.id = ?";
		List<Object> paras = new ArrayList<Object>();
		paras.add(parentUserId);
		if (startDate != null) {
			hql += " and createtime >= ? ";
			paras.add(DateUtils.getBeginningOfADay(startDate));
		}
		if (endDate != null) {
			hql += " and createtime <= ? ";
			paras.add(DateUtils.getEndOfADay(endDate));
		}
		return super.countByHql(hql, paras.toArray());
	}
	
	public void  updateLastLoginTime(UserDTO dto){
		if(dto.getId()!=null){
			String hql="update user u set u.lastLoginTime=? where id=?";
			List<Object> paras = new ArrayList<Object>();
			paras.add(dto.getLastLoginTime());
			paras.add(dto.getId());
			super.executeSQLUpdate(hql, paras.toArray());
		}
	}
}
